/*
 * Cute4jSwing.h  0.4.0 / Nov 17, 2010
 *
 * Copyright (c) 2010 - 2011, cute4j.com and contributors.
 *
 * The contents of this file are subject to the LGPL, version 2.1, license
 * distributed with the source code in the file LICENSE.txt
 */
#ifndef CUTE4JSWING_H
#define CUTE4JSWING_H

/*!
 * \brief Common header file for the Swing module.
 *
 * \author Slobodan Vrkacevic
 * \version 0.4.0
 */

// Cute4jSwing :: Includes. ----------------------------------------------------

#include <QtGui>

#include "Cute4jCore.h"

#include "JNISwingWrapper.h"
#include "SwingString.h"
#include "QColorAdapter.h"
#include "DimensionObject.h"
#include "RectangleObject.h"
#include "QFontAdapter.h"
#include "QEventsAdapter.h"
#include "SwingMetaObject.h"
#include "SwingUtilitiesDelegate.h"

// Cute4jSwing :: Global Functions. --------------------------------------------

template<typename T>
inline T invokeMember(QObject *obj, const char *method, const char *type,
                      QGenericArgument val0 = QGenericArgument(),
                      QGenericArgument val1 = QGenericArgument(),
                      QGenericArgument val2 = QGenericArgument(),
                      QGenericArgument val3 = QGenericArgument(),
                      QGenericArgument val4 = QGenericArgument(),
                      QGenericArgument val5 = QGenericArgument(),
                      QGenericArgument val6 = QGenericArgument(),
                      QGenericArgument val7 = QGenericArgument(),
                      QGenericArgument val8 = QGenericArgument(),
                      QGenericArgument val9 = QGenericArgument())
{
  T t;
  #ifdef CUTE4J_DEBUG
    bool memberInvoked =
  #endif // CUTE4J_DEBUG
      SwingMetaObject::invokeMember(obj, method, type, static_cast<void *>(&t),
                                    &val0, &val1, &val2, &val3, &val4, &val5,
                                    &val6, &val7, &val8, &val9);
  #ifdef CUTE4J_DEBUG
    Q_ASSERT(memberInvoked);
  #endif // CUTE4J_DEBUG
  return t;
}

template<typename T>
inline T invokeStaticMember(int classID, int methodID, const char *type,
                            QGenericArgument val0 = QGenericArgument(),
                            QGenericArgument val1 = QGenericArgument(),
                            QGenericArgument val2 = QGenericArgument(),
                            QGenericArgument val3 = QGenericArgument(),
                            QGenericArgument val4 = QGenericArgument(),
                            QGenericArgument val5 = QGenericArgument(),
                            QGenericArgument val6 = QGenericArgument(),
                            QGenericArgument val7 = QGenericArgument(),
                            QGenericArgument val8 = QGenericArgument(),
                            QGenericArgument val9 = QGenericArgument())
{
  T t;
  #ifdef CUTE4J_DEBUG
    bool memberInvoked =
  #endif // CUTE4J_DEBUG
      SwingMetaObject::invokeStaticMember(classID, methodID, type,
                                          static_cast<void *>(&t), &val0,
                                          &val1, &val2, &val3, &val4, &val5,
                                          &val6, &val7, &val8, &val9);
  #ifdef CUTE4J_DEBUG
    Q_ASSERT(memberInvoked);
  #endif // CUTE4J_DEBUG
  return t;
}

// Cute4jSwing :: Explicit Function Template Instantiations. -------------------

template inline jobject invokeMember<jobject>(
                          QObject *, const char *, const char *,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument);
template inline jstring invokeMember<jstring>(
                          QObject *, const char *, const char *,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument);
template inline jint invokeMember<jint>(
                          QObject *, const char *, const char *,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument);
template inline jboolean invokeMember<jboolean>(
                          QObject *, const char *, const char *,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument);

template inline jobject invokeStaticMember<jobject>(
                          int, int, const char *, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument);
template inline jstring invokeStaticMember<jstring>(
                          int, int, const char *, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument);
template inline jobjectArray invokeStaticMember<jobjectArray>(
                          int, int, const char *, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument);
template inline jint invokeStaticMember<jint>(
                          int, int, const char *, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument);
template inline jboolean invokeStaticMember<jboolean>(
                          int, int, const char *, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument,
                          QGenericArgument, QGenericArgument, QGenericArgument);

// Cute4jSwing :: Macro Definitions. -------------------------------------------

#define JBOOLEAN_ARG(boolean) Q_ARG(jboolean, boolean)
#define JCHAR_ARG(char) Q_ARG(jchar, char)
#define JSHORT_ARG(short) Q_ARG(jshort, short)
#define JINT_ARG(int) Q_ARG(jint, int)
#define JLONG_ARG(long) Q_ARG(jlong, long)
#define JFLOAT_ARG(float) Q_ARG(jfloat, float)
#define JDOUBLE_ARG(double) Q_ARG(jdouble, double)
#define JOBJECT_ARG(object) Q_ARG(jobject, GlobalJObject(env, object).ref())
#define JSTRING_ARG(string) Q_ARG(jstring, GlobalJString(env, string).ref())
#define JCLASS_ARG(class) Q_ARG(jclass, GlobalJClass(env, class).ref())
#define JBYTEARRAY_ARG(byteArray) \
    Q_ARG(jbyteArray, GlobalJByteArray(env, byteArray).ref())
#define SWING_ENV_ARG Q_ARG(JNIEnv *, SWING_ENV)

#ifndef CUTE4J_DEBUG
  #define SWING_REENTRANT(method, ...) \
      if (!JNISwingWrapper::isSwingThread(env)) { \
        QMetaObject::invokeMethod(this, #method, \
                                  Qt::BlockingQueuedConnection, \
                                  QGenericReturnArgument(), __VA_ARGS__); \
        return; \
      }
#endif // CUTE4J_DEBUG

#ifndef CUTE4J_DEBUG
  #define SWING_STATIC_REENTRANT(class, method, ...) \
      if (!JNISwingWrapper::isSwingThread(env)) { \
        SwingMetaObject::invokeStaticMember( \
                               SwingMetaObject::class##_classID, \
                               SwingMetaObject::class##_##method##_methodID, \
                               __VA_ARGS__); \
        return; \
      }
#endif // CUTE4J_DEBUG

#ifdef CUTE4J_DEBUG
  #define SWING_REENTRANT(method, ...) \
      if (!JNISwingWrapper::isSwingThread(env)) { \
        bool methodInvoked = \
             QMetaObject::invokeMethod(this, #method, \
                                       Qt::BlockingQueuedConnection, \
                                       QGenericReturnArgument(), __VA_ARGS__); \
        Q_ASSERT(methodInvoked); \
        return; \
      }
#endif // CUTE4J_DEBUG

#ifdef CUTE4J_DEBUG
  #define SWING_STATIC_REENTRANT(class, method, ...) \
      if (!JNISwingWrapper::isSwingThread(env)) { \
        bool methodInvoked = \
          SwingMetaObject::invokeStaticMember( \
                                 SwingMetaObject::class##_classID, \
                                 SwingMetaObject::class##_##method##_methodID, \
                              __VA_ARGS__); \
        Q_ASSERT(methodInvoked); \
        return; \
      }
#endif // CUTE4J_DEBUG

#define SWING_REENTRANT_RETURN(method, type, ...) \
    if (!JNISwingWrapper::isSwingThread(env)) { \
      return invokeMember<type>(this, #method, #type, __VA_ARGS__); \
    }

#define SWING_STATIC_REENTRANT_RETURN(class, method, type, ...) \
    if (!JNISwingWrapper::isSwingThread(env)) { \
      return invokeStaticMember<type>( \
                                 SwingMetaObject::class##_classID, \
                                 SwingMetaObject::class##_##method##_methodID, \
                                 #type, __VA_ARGS__); \
    }

#endif  // CUTE4JSWING_H
